#ifndef TIEC_CONCURRENT_DATA_H
#define TIEC_CONCURRENT_DATA_H

#include <algorithm>
#include <shared_mutex>
#include <vector>
#include <unordered_map>
#include <stack>
#include <unordered_set>
#include <queue>
#include <deque>
#include <iterator>

#include "macro.h"

namespace NS_TIEC {
  /// 线程安全列表
  template<typename T>
  class ConcurrentList {
  public:
    ConcurrentList() = default;

    ConcurrentList(const ConcurrentList<T>& other) {
      LOCK_SHARED(other.mutex_);
      vector_ = other.vector_;
    }

    ConcurrentList(const ConcurrentList<T>&& other) noexcept {
      LOCK_UNIQUE(other.mutex_);
      vector_ = std::move(other.vector_);
    }

    ConcurrentList& operator=(const ConcurrentList<T>& other) {
      if (this != &other) {
        LOCK_SCOPED(mutex_, other.mutex_);
        vector_ = other.vector_;
      }
      return *this;
    }

    ConcurrentList& operator=(const ConcurrentList<T>&& other) noexcept {
      LOCK_UNIQUE(other.mutex_);
      vector_ = std::move(other.vector_);
      return *this;
    }

    template <typename... Elements>
    static ConcurrentList<T> of(Elements&&... elements) {
      ConcurrentList<T> result;
      (result.add(std::forward<Elements>(elements)), ...);
      return result;
    }

    T& at(const size_t index) {
      LOCK_SHARED(mutex_);
      return vector_.at(index);
    }

    const T& at(const size_t index) const {
      LOCK_SHARED(mutex_);
      return vector_.at(index);
    }

    T& operator[](const size_t index) {
      LOCK_SHARED(mutex_);
      return vector_[index];
    }

    const T& operator[](const size_t index) const {
      LOCK_SHARED(mutex_);
      return vector_[index];
    }

    template<typename U>
    void add(U&& element) {
      LOCK_UNIQUE(mutex_);
      vector_.push_back(std::forward<U>(element));
    }

    void addAll(const ConcurrentList<T>& other) {
      LOCK_UNIQUE(mutex_);
      other.forEach([this](const T& element) {
        vector_.push_back(element);
      });
    }

    void set(size_t index, T&& element) {
      LOCK_UNIQUE(mutex_);
      if (index > vector_.size()) return;
      vector_[index] = std::forward<T>(element);
    }

    bool insert(size_t index, T&& element) {
      LOCK_UNIQUE(mutex_);
      if (index > vector_.size()) return false;
      vector_.insert(vector_.begin() + index, std::forward<T>(element));
      return true;
    }

    template<typename U>
    bool remove(U&& element) {
      LOCK_UNIQUE(mutex_);
      auto it = std::find(vector_.begin(), vector_.end(), std::forward<U>(element));
      if (it != vector_.end()) {
        vector_.erase(it);
        return true;
      }
      return false;
    }

    bool removeAt(int index) {
      LOCK_UNIQUE(mutex_);
      if (index > vector_.size()) return false;
      vector_.erase(vector_.begin() + index);
      return true;
    }

    template<typename Func, typename = std::enable_if_t<is_lambda_with_signature<Func, bool, T&>>>
    void removeFirst(Func&& predicate) {
      LOCK_UNIQUE(mutex_);
      auto it = std::find_if(vector_.begin(), vector_.end(), predicate);
      if (it != vector_.end()) {
        vector_.erase(it);
      }
    }

    template<typename Func, typename = std::enable_if_t<is_lambda_with_signature<Func, bool, T&>>>
    ConcurrentList<T> removeAll(Func&& predicate) {
      LOCK_UNIQUE(mutex_);
      auto partition_it = std::partition(vector_.begin(), vector_.end(), predicate);
      ConcurrentList<T> removed;
      for (auto it = vector_.begin();it < partition_it;++it) {
        removed.add(*it);
      }
      vector_.erase(vector_.begin(), partition_it);
      return removed;
    }

    T last() {
      LOCK_SHARED(mutex_);
      if (vector_.empty()) {
        return {};
      }
      return vector_.back();
    }

    template<typename Func, typename = std::enable_if_t<is_lambda_with_signature<Func, void, const T&>>>
    void forEach(Func&& consumer) const {
      LOCK_SHARED(mutex_);
      for (const auto& item : vector_) {
        std::forward<Func>(consumer)(item);
      }
    }

    template<typename Func, typename = std::enable_if_t<is_lambda_with_signature<Func, void, T&>>>
    void forEach(Func&& consumer) {
      LOCK_UNIQUE(mutex_);
      for (auto& item : vector_) {
        std::forward<Func>(consumer)(item);
      }
    }

    template<typename Func, typename = std::enable_if_t<is_lambda_with_signature<Func, bool, T&>>>
    void forEachUntil(Func&& consumer) {
      LOCK_UNIQUE(mutex_);
      for (auto& item : vector_) {
        if (std::forward<Func>(consumer)(item)) {
          return;
        }
      }
    }

    template<typename Func, typename = std::enable_if_t<is_lambda_with_signature<Func, bool, const T&>>>
    T findFirst(Func&& filter) {
      LOCK_SHARED(mutex_);
      auto it =  std::find_if(vector_.begin(), vector_.end(), filter);
      if (it != vector_.end()) {
        return *it;
      }
      return {};
    }

    template<typename U>
    bool contains(U&& element) {
      return std::find(vector_.begin(), vector_.end(), std::forward<U>(element)) != vector_.end();
    }

    template<typename Func, typename = std::enable_if_t<is_lambda_with_signature<Func, bool, const T&>>>
    bool containsIf(Func&& filter) {
      LOCK_SHARED(mutex_);
      return std::any_of(vector_.begin(), vector_.end(), filter);
    }

    template<typename U, typename Func, typename = std::enable_if_t<is_lambda_with_signature<Func, U, const T&>>>
    ConcurrentList<U> transform(Func&& transformer) const {
      ConcurrentList<U> result;
      for (const auto& item : vector_) {
        result.add(std::forward<Func>(transformer)(item));
      }
      return result;
    }

    void clear() {
      LOCK_UNIQUE(mutex_);
      vector_.clear();
    }

    bool empty() const {
      LOCK_SHARED(mutex_);
      return vector_.empty();
    }

    size_t size() const {
      LOCK_SHARED(mutex_);
      return vector_.size();
    }

    ConcurrentList<T> subList(const size_t start, const size_t count) {
      if (start + count > vector_.size()) {
        throw std::out_of_range("subList: out of range [0, " + size() + ")");
      }
      ConcurrentList<T> result;
      for (size_t i = start; i < start + count; i++) {
        result.add(vector_[i]);
      }
      return result;
    }

    typename std::vector<T>::iterator begin() {
      LOCK_SHARED(mutex_);
      return vector_.begin();
    }

    typename std::vector<T>::iterator end() {
      LOCK_SHARED(mutex_);
      return vector_.end();
    }

    typename std::vector<T>::const_iterator begin() const {
      LOCK_SHARED(mutex_);
      return vector_.begin();
    }

    typename std::vector<T>::const_iterator end() const {
      LOCK_SHARED(mutex_);
      return vector_.end();
    }
  private:
    mutable std::shared_mutex mutex_;
    std::vector<T> vector_;
  };

  /// 线程安全哈希表
  template<typename K, typename V, typename Hash = std::hash<K>, typename KeyEqual = std::equal_to<K>>
  class ConcurrentHashMap {
  public:
    ConcurrentHashMap() = default;

    ConcurrentHashMap(const ConcurrentHashMap<K, V, Hash, KeyEqual>& other) {
      LOCK_SHARED(other.mutex_);
      map_ = other.map_;
    }

    ConcurrentHashMap(ConcurrentHashMap<K, V, Hash, KeyEqual>&& other) noexcept {
      LOCK_UNIQUE(other.mutex_);
      map_ = std::move(other.map_);
    }

    ConcurrentHashMap<K, V, Hash, KeyEqual>& operator=(const ConcurrentHashMap<K, V, Hash, KeyEqual>& other) {
      if (this != &other) {
        LOCK_SCOPED(mutex_, other.mutex_);
        map_ = other.map_;
      }
      return *this;
    }

    ConcurrentHashMap<K, V, Hash, KeyEqual>& operator=(ConcurrentHashMap<K, V, Hash, KeyEqual>&& other) noexcept {
      LOCK_UNIQUE(other.mutex_);
      map_ = std::move(other.map_);
      return *this;
    }

    V& get(const K& key) {
      LOCK_SHARED(mutex_);
      return map_.at(key);
    }

    const V& get(const K& key) const {
      LOCK_SHARED(mutex_);
      return map_.at(key);
    }

    V& operator[](const K& key) {
      LOCK_SHARED(mutex_);
      return map_.at(key);
    }

    const V& operator[](const K& key) const {
      LOCK_SHARED(mutex_);
      return map_.at(key);
    }

    template<typename KType, typename VType>
    void put(KType&& key, VType&& value) {
      LOCK_UNIQUE(mutex_);
      map_.emplace(std::forward<KType>(key), std::forward<VType>(value));
    }

    void putAll(const ConcurrentHashMap<K, V, Hash, KeyEqual>& other) {
      LOCK_UNIQUE(mutex_);
      for (const PAIR<K, V>& pair : other) {
        map_.emplace(pair.first, pair.second);
      }
    }

    V getOrDefault(const K& key, const V& def_value) const {
      LOCK_SHARED(mutex_);
      auto it = map_.find(key);
      if (it != map_.end()) {
        return it->second;
      }
      return def_value;
    }

    bool contains(const K& key) const {
      LOCK_SHARED(mutex_);
      return map_.find(key) != map_.end();
    }

    bool remove(const K& key) {
      LOCK_UNIQUE(mutex_);
      return map_.erase(key) > 0;
    }

    template<typename Func, typename = std::enable_if_t<is_lambda_with_signature<Func, void, const K&, const V&>>>
    void forEach(Func&& consumer) const {
      LOCK_SHARED(mutex_);
      for (const auto& [key, value] : map_) {
        std::forward<Func>(consumer)(key, value);
      }
    }

    template<typename Func, typename = std::enable_if_t<is_lambda_with_signature<Func, void, const K&, V&>>>
    void forEach(Func&& consumer) {
      LOCK_UNIQUE(mutex_);
      for (auto& [key, value] : map_) {
        std::forward<Func>(consumer)(key, value);
      }
    }

    template<typename Func, typename = std::enable_if_t<is_lambda_with_signature<Func, bool, const K&, const V&>>>
    void forEachUntil(Func&& consumer) {
      LOCK_UNIQUE(mutex_);
      for (auto& [key, value] : map_) {
        if (std::forward<Func>(consumer)(key, value)) {
          return;
        }
      }
    }

    ConcurrentList<K> keys() const {
      LOCK_SHARED(mutex_);
      ConcurrentList<K> keyConcurrentList;
      for (const auto& [key, value] : map_) {
        keyConcurrentList.add(key);
      }
      return keyConcurrentList;
    }

    ConcurrentList<V> values() const {
      LOCK_SHARED(mutex_);
      ConcurrentList<V> valueConcurrentList;
      for (const auto& [key, value] : map_) {
        valueConcurrentList.add(value);
      }
      return valueConcurrentList;
    }

    bool empty() const {
      LOCK_SHARED(mutex_);
      return map_.empty();
    }

    size_t size() const {
      LOCK_SHARED(mutex_);
      return map_.size();
    }

    void clear() {
      LOCK_UNIQUE(mutex_);
      map_.clear();
    }

    typename std::unordered_map<K, V, Hash, KeyEqual>::iterator begin() {
      LOCK_SHARED(mutex_);
      return map_.begin();
    }

    typename std::unordered_map<K, V, Hash, KeyEqual>::iterator end() {
      LOCK_SHARED(mutex_);
      return map_.end();
    }

    typename std::unordered_map<K, V, Hash, KeyEqual>::const_iterator begin() const {
      LOCK_SHARED(mutex_);
      return map_.begin();
    }

    typename std::unordered_map<K, V, Hash, KeyEqual>::const_iterator end() const {
      LOCK_SHARED(mutex_);
      return map_.end();
    }

  private:
    mutable std::shared_mutex mutex_;
    std::unordered_map<K, V, Hash, KeyEqual> map_;
  };

  /// 线程安全集合数据结构
  template<typename T, typename Hash = std::hash<T>, typename KeyEqual = std::equal_to<T>>
  class ConcurrentSet {
  public:
    ConcurrentSet() = default;

    ConcurrentSet(const ConcurrentSet<T, Hash, KeyEqual>& other) {
      LOCK_SHARED(other.mutex_);
      set_ = other.set_;
    }

    ConcurrentSet(ConcurrentSet<T, Hash, KeyEqual>&& other) noexcept {
      LOCK_UNIQUE(other.mutex_);
      set_ = std::move(other.set_);
    }

    ConcurrentSet& operator=(const ConcurrentSet<T, Hash, KeyEqual>& other) {
      if (this != &other) {
        LOCK_SCOPED(mutex_, other.mutex_);
        set_ = other.set_;
      }
      return *this;
    }

    ConcurrentSet& operator=(ConcurrentSet<T, Hash, KeyEqual>&& other) noexcept {
      LOCK_UNIQUE(other.mutex_);
      set_ = std::move(other.set_);
      return *this;
    }

    template<typename U>
    void add(U&& element) {
      LOCK_UNIQUE(mutex_);
      set_.emplace(std::forward<U>(element));
    }

    void addAll(const ConcurrentSet<T, Hash, KeyEqual>& other) {
      LOCK_UNIQUE(mutex_);
      for (const T& element : other) {
        set_.emplace(element);
      }
    }

    template<typename U>
    bool remove(U&& element) {
      LOCK_UNIQUE(mutex_);
      auto it = std::find(set_.begin(), set_.end(), std::forward<U>(element));
      if (it != set_.end()) {
        set_.erase(it);
        return true;
      }
      return false;
    }

    bool has(const T& element) {
      LOCK_SHARED(mutex_);
      return std::find(set_.begin(), set_.end(), element) != set_.end();
    }

    size_t size() const {
      LOCK_SHARED(mutex_);
      return set_.size();
    }

    bool empty() const {
      LOCK_SHARED(mutex_);
      return set_.empty();
    }

    T findFirst(FUNCTION<bool(const T&)> filter) {
      for (const auto& item : set_) {
        if (filter(item)) {
          return item;
        }
      }
      return {};
    }

    template<typename Func, typename = std::enable_if_t<is_lambda_with_signature<Func, void, const T&>>>
    void forEach(Func&& consumer) const {
      LOCK_SHARED(mutex_);
      for (const auto& item : set_) {
        std::forward<Func>(consumer)(item);
      }
    }

    template<typename Func, typename = std::enable_if_t<is_lambda_with_signature<Func, bool, const T&>>>
    void forEachUntil(Func&& consumer) {
      LOCK_UNIQUE(mutex_);
      for (auto& item : set_) {
        if (std::forward<Func>(consumer)(item)) {
          return;
        }
      }
    }

    typename std::unordered_set<T, Hash, KeyEqual>::iterator begin() {
      LOCK_SHARED(mutex_);
      return set_.begin();
    }

    typename std::unordered_set<T, Hash, KeyEqual>::iterator end() {
      LOCK_SHARED(mutex_);
      return set_.end();
    }

    typename std::unordered_set<T, Hash, KeyEqual>::const_iterator begin() const {
      LOCK_SHARED(mutex_);
      return set_.begin();
    }

    typename std::unordered_set<T, Hash, KeyEqual>::const_iterator end() const {
      LOCK_SHARED(mutex_);
      return set_.end();
    }
  private:
    mutable std::shared_mutex mutex_;
    std::unordered_set<T, Hash, KeyEqual> set_;
  };

  /// 栈数据结构
  template<typename T>
  class ConcurrentStack {
  public:
    ConcurrentStack() = default;

    ConcurrentStack(const ConcurrentStack<T>& other) {
      LOCK_SHARED(other.mutex_);
      stack_ = other.stack_;
    }

    ConcurrentStack(ConcurrentStack<T>&& other) noexcept {
      LOCK_UNIQUE(other.mutex_);
      stack_ = std::move(other.stack_);
    }

    ConcurrentStack& operator=(const ConcurrentStack<T>& other) {
      if (this != &other) {
        LOCK_SCOPED(mutex_, other.mutex_);
        stack_ = other.stack_;
      }
      return *this;
    }

    ConcurrentStack& operator=(ConcurrentStack<T>&& other) noexcept {
      LOCK_UNIQUE(other.mutex_);
      stack_ = std::move(other.stack_);
      return *this;
    }

    template<typename U>
    void push(U&& value) {
      LOCK_UNIQUE(mutex_);
      stack_.push(std::forward<U>(value));
    }

    T& pop() {
      LOCK_UNIQUE(mutex_);
      T& top = stack_.top();
      stack_.pop();
      return top;
    }

    const T& pop() const {
      LOCK_UNIQUE(mutex_);
      T& top = stack_.top();
      stack_.pop();
      return top;
    }

    T& top() {
      LOCK_SHARED(mutex_);
      return stack_.top();
    }

    const T& top() const {
      LOCK_SHARED(mutex_);
      return stack_.top();
    }

    size_t size() const {
      LOCK_SHARED(mutex_);
      return stack_.size();
    }

    void clear() {
      LOCK_UNIQUE(mutex_);
      stack_.clear();
    }

    template<typename Func, typename = std::enable_if_t<is_lambda_with_signature<Func, void, const T&>>>
    void forEach(Func&& consumer) const {
      LOCK_SHARED(mutex_);
      for (const auto& value : stack_) {
        std::forward<Func>(consumer)(value);
      }
    }

    template<typename Func, typename = std::enable_if_t<is_lambda_with_signature<Func, void, T&>>>
    void forEach(Func&& consumer) {
      LOCK_UNIQUE(mutex_);
      for (auto& value : stack_) {
        std::forward<Func>(consumer)(value);
      }
    }

    template<typename Func, typename = std::enable_if_t<is_lambda_with_signature<Func, bool, const T&>>>
    bool containsIf(Func&& consumer) {
      return std::any_of(stack_.begin(), stack_.end(), consumer);
    }
  private:
    mutable std::shared_mutex mutex_;
    std::stack<T> stack_;
  };

  /// 队列数据结构
  template<typename T>
  class ConcurrentQueue {
  public:
    ConcurrentQueue() = default;

    ConcurrentQueue(const ConcurrentQueue<T>& other) {
      LOCK_SHARED(other.mutex_);
      queue_ = other.queue_;
    }

    ConcurrentQueue(ConcurrentQueue<T>&& other) noexcept {
      LOCK_UNIQUE(other.mutex_);
      queue_ = std::move(other.queue_);
    }

    ConcurrentQueue& operator=(const ConcurrentQueue<T>& other) {
      if (this != &other) {
        LOCK_SCOPED(mutex_, other.mutex_);
        queue_ = other.queue_;
      }
      return *this;
    }

    ConcurrentQueue& operator=(ConcurrentQueue<T>&& other) noexcept {
      LOCK_UNIQUE(other.mutex_);
      queue_ = std::move(other.queue_);
      return *this;
    }

    template<typename U>
    void enqueue(U&& value) {
      LOCK_UNIQUE(mutex_);
      queue_.push(std::forward<U>(value));
    }

    bool dequeue(T& value) {
      LOCK_UNIQUE(mutex_);
      if (queue_.empty()) {
        return false;
      }
      value = std::move(queue_.front());
      queue_.pop();
      return true;
    }

    T tryConcurrentDequeue() {
      LOCK_UNIQUE(mutex_);
      if (queue_.empty()) {
        return T{};
      }
      T value = std::move(queue_.front());
      queue_.pop();
      return value;
    }

    bool peek(T& value) const {
      LOCK_SHARED(mutex_);
      if (queue_.empty()) {
        return false;
      }
      value = queue_.front();
      return true;
    }

    T front() const {
      LOCK_SHARED(mutex_);
      if (queue_.empty()) {
        return T{};
      }
      return queue_.front();
    }

    T back() const {
      LOCK_SHARED(mutex_);
      if (queue_.empty()) {
        return T{};
      }
      return queue_.back();
    }

    bool empty() const {
      LOCK_SHARED(mutex_);
      return queue_.empty();
    }

    size_t size() const {
      LOCK_SHARED(mutex_);
      return queue_.size();
    }

    void clear() {
      LOCK_UNIQUE(mutex_);
      while (!queue_.empty()) {
        queue_.pop();
      }
    }

    template<typename Func, typename = std::enable_if_t<is_lambda_with_signature<Func, void, const T&>>>
    void forEach(Func&& consumer) const {
      LOCK_SHARED(mutex_);
      std::queue<T> temp = queue_;
      while (!temp.empty()) {
        std::forward<Func>(consumer)(temp.front());
        temp.pop();
      }
    }
  private:
    mutable std::shared_mutex mutex_;
    std::queue<T> queue_;
  };

  /// 双端队列数据结构
  template<typename T>
  class ConcurrentDeque {
  public:
    ConcurrentDeque() = default;

    ConcurrentDeque(const ConcurrentDeque<T>& other) {
      LOCK_SHARED(other.mutex_);
      deque_ = other.deque_;
    }

    ConcurrentDeque(ConcurrentDeque<T>&& other) noexcept {
      LOCK_UNIQUE(other.mutex_);
      deque_ = std::move(other.deque_);
    }

    ConcurrentDeque& operator=(const ConcurrentDeque<T>& other) {
      if (this != &other) {
        LOCK_SCOPED(mutex_, other.mutex_);
        deque_ = other.deque_;
      }
      return *this;
    }

    ConcurrentDeque& operator=(ConcurrentDeque<T>&& other) noexcept {
      LOCK_UNIQUE(other.mutex_);
      deque_ = std::move(other.deque_);
      return *this;
    }

    template<typename U>
    void pushBack(U&& value) {
      LOCK_UNIQUE(mutex_);
      deque_.push_back(std::forward<U>(value));
    }

    template<typename U>
    void pushFront(U&& value) {
      LOCK_UNIQUE(mutex_);
      deque_.push_front(std::forward<U>(value));
    }

    bool popBack(T& value) {
      LOCK_UNIQUE(mutex_);
      if (deque_.empty()) {
        return false;
      }
      value = std::move(deque_.back());
      deque_.pop_back();
      return true;
    }

    bool popFront(T& value) {
      LOCK_UNIQUE(mutex_);
      if (deque_.empty()) {
        return false;
      }
      value = std::move(deque_.front());
      deque_.pop_front();
      return true;
    }

    T tryPopBack() {
      LOCK_UNIQUE(mutex_);
      if (deque_.empty()) {
        return T{};
      }
      T value = std::move(deque_.back());
      deque_.pop_back();
      return value;
    }

    T tryPopFront() {
      LOCK_UNIQUE(mutex_);
      if (deque_.empty()) {
        return T{};
      }
      T value = std::move(deque_.front());
      deque_.pop_front();
      return value;
    }

    T front() const {
      LOCK_SHARED(mutex_);
      if (deque_.empty()) {
        return T{};
      }
      return deque_.front();
    }

    T back() const {
      LOCK_SHARED(mutex_);
      if (deque_.empty()) {
        return T{};
      }
      return deque_.back();
    }

    T at(size_t index) const {
      LOCK_SHARED(mutex_);
      if (index >= deque_.size()) {
        return T{};
      }
      return deque_.at(index);
    }

    template<typename U>
    bool insert(size_t index, U&& value) {
      LOCK_UNIQUE(mutex_);
      if (index > deque_.size()) {
        return false;
      }
      deque_.insert(deque_.begin() + index, std::forward<U>(value));
      return true;
    }

    bool erase(size_t index) {
      LOCK_UNIQUE(mutex_);
      if (index >= deque_.size()) {
        return false;
      }
      deque_.erase(deque_.begin() + index);
      return true;
    }

    bool empty() const {
      LOCK_SHARED(mutex_);
      return deque_.empty();
    }

    size_t size() const {
      LOCK_SHARED(mutex_);
      return deque_.size();
    }

    void clear() {
      LOCK_UNIQUE(mutex_);
      deque_.clear();
    }

    template<typename Func, typename = std::enable_if_t<is_lambda_with_signature<Func, void, const T&>>>
    void forEach(Func&& consumer) const {
      LOCK_SHARED(mutex_);
      for (const auto& item : deque_) {
        std::forward<Func>(consumer)(item);
      }
    }

    template<typename Func, typename = std::enable_if_t<is_lambda_with_signature<Func, bool, T&>>>
    void forEach(Func&& consumer) {
      LOCK_UNIQUE(mutex_);
      for (auto& item : deque_) {
        std::forward<Func>(consumer)(item);
      }
    }

    template<typename Func, typename = std::enable_if_t<is_lambda_with_signature<Func, bool, const T&>>>
    T findFirst(Func&& filter) const {
      LOCK_SHARED(mutex_);
      auto it = std::find_if(deque_.begin(), deque_.end(), filter);
      if (it != deque_.end()) {
        return *it;
      }
      return T{};
    }

    template<typename U>
    bool contains(U&& element) const {
      LOCK_SHARED(mutex_);
      return std::find(deque_.begin(), deque_.end(), std::forward<U>(element)) != deque_.end();
    }

  private:
    mutable std::shared_mutex mutex_;
    std::deque<T> deque_;
  };
} // NS_TIEC

#endif //TIEC_CONCURRENT_DATA_H
